#!/bin/bash
###########################################################################
if ! [ -e UTILS/common.sh ]; then
	echo "You must run this script only from the base directory."
	exit
fi

source UTILS/common.sh
set -e
#print_credentials
check_arguments $1 $2 $3 $4 $5 $6
initial_checks
setup_directory_structure
recalculate_global_params
source UTILS/sanity_checks.sh	# Perform initial sanity checks
############################################################################
# gem5 python parameters

set +e
OPTION=$(grep "#define PRINT_PACKET_FLOW" $GEM5_BASE_DIR/src/mem/port.cc)
if [[ $OPTION == "#define PRINT_PACKET_FLOW" ]]; then
	print_war "Extracting packet flow is enabled, you can disable it by commenting #define PRINT_PACKET_FLOW in $GEM5_BASE_DIR/src/mem/port.hh,"
	print_war "Then you have to rebuild the project again."
fi

OPTION=$(grep "#define ENABLE_PACKET_LOG" $GEM5_BASE_DIR/src/mem/noncoherent_xbar.cc)
if [[ $OPTION == "#define ENABLE_PACKET_LOG" ]]; then
	print_war "Packet logging is enabled, you can disable it by commenting #define ENABLE_PACKET_LOG in $GEM5_BASE_DIR/src/mem/noncoherent_xbar.cc,"
	print_war "Then you have to rebuild the project again."
fi
set -e

OPTION=$(grep "#define GATHER_TRACES" $GEM5_BASE_DIR/src/mem/comm_monitor.cc)
if [[ $OPTION == "#define GATHER_TRACES" ]]; then
    print_war "Gathering traces is enabled, you can disable it by commenting #define GATHER_TRACES in $GEM5_BASE_DIR/src/mem/comm_monitor.cc,"
    print_war "Then you have to rebuild the project again."
fi
set -e


echo -e "
# Automatically generated by Erfan
#*********************************
$(param_python str ARCH $ARCH)
$(param_python str OUTDIR $M5_OUTDIR)
$(param_python int N_INIT_PORT $N_INIT_PORT)
$(param_python int N_TARG_PORT $N_TARG_PORT)
$(param_python int GEM5_VAULT_WBUFFER_SIZE $GEM5_VAULT_WBUFFER_SIZE)
$(param_python int GEM5_VAULT_RBUFFER_SIZE $GEM5_VAULT_RBUFFER_SIZE)
$(param_python int GEM5_NUMCPU $GEM5_NUMCPU)
$(param_python str GEM5_ADDR_MAPPING $GEM5_ADDR_MAPPING)
$(param_python str GEM5_ENABLE_COMM_MONITORS $GEM5_ENABLE_COMM_MONITORS)
$(param_python str GEM5_PERIODIC_STATS_DUMP $GEM5_PERIODIC_STATS_DUMP)
$(param_python int GEM5_PERIODIC_STATS_DUMP_PERIOD $GEM5_PERIODIC_STATS_DUMP_PERIOD)
$(param_python str DRAM_LAYER_SIZE_MB "${DRAM_LAYER_SIZE_MB}MB")
$(param_python str DRAM_CHANNEL_SIZE_MB "${DRAM_CHANNEL_SIZE_MB}MB")
$(param_python int DRAM_CHANNEL_SIZE_INT ${DRAM_CHANNEL_SIZE_B})
$(param_python int DRAM_BUS_WIDTH $DRAM_BUS_WIDTH)
$(param_python int HOST_BURST_SIZE_B $HOST_BURST_SIZE_B)
$(param_python int SMC_BURST_SIZE_B $SMC_BURST_SIZE_B)
$(param_python int AXI_DATA_W $AXI_DATA_W )
$(param_python str VAULT_CLOCK_FREQUENCY "`perl -l -e "print (1.0/$DRAM_tCK)"`GHz")
$(param_python str SMCXBAR_CLOCK_FREQUENCY "`perl -l -e "print (1.0/$CLK_PERIOD_SYS)"`GHz")
$(param_python str HOST_CLOCK_FREQUENCY "${HOST_CLOCK_FREQUENCY_GHz}GHz")
$(param_python str SERIALLINKS_CLOCK_FREQUENCY "${SERIALLINKS_CLOCK_FREQUENCY_GHz}GHz")
$(param_python int SERIALLINKS_NUM_LINKS $SERIALLINKS_NUM_LINKS)
$(param_python int SERIALLINKS_NUM_LANES_PER_LINK $SERIALLINKS_NUM_LANES_PER_LINK)
$(param_python str DRAM_PAGE_POLICY $DRAM_PAGE_POLICY)
$(param_python int DRAM_BURST_LENGTH `perl -l -e "print ($AXI_DATA_W/$DRAM_BUS_WIDTH)"`)
$(param_python str DRAM_ROW_BUFFER_SIZE "`perl -l -e "print (2**$DRAM_column_size * $DRAM_BUS_WIDTH / 8 )"`B")
$(param_python int DRAM_BANKS_PER_VAULT $DRAM_BANKS_PER_VAULT)
$(param_python int N_MEM_DIES $N_MEM_DIES)
$(param_python int DRAM_BANKS_PER_DIE $DRAM_BANKS_PER_DIE)
$(param_python str DRAM_tBURST "`perl -l -e "print (($AXI_DATA_W/$DRAM_BUS_WIDTH)*$DRAM_tCK/2)"`ns" )
$(param_python str DRAM_tRCD "${DRAM_tRCD}ns" )
$(param_python str DRAM_tWR "${DRAM_tWR}ns" )
$(param_python str DRAM_tCL "${DRAM_tCL}ns" )
$(param_python str DRAM_tCK "${DRAM_tCK}ns" )
$(param_python str DRAM_tRP "${DRAM_tRP}ns" )
$(param_python str DRAM_tRAS "${DRAM_tRAS}ns" )
$(param_python str DRAM_tRTP "${DRAM_tRTP}ns" )
$(param_python str DRAM_tRRD "${DRAM_tRRD}ns" )
$(param_python str DRAM_tRFC "${DRAM_tRFC}ns" )
$(param_python str DRAM_tREFI "${DRAM_tREFI}us" )
$(param_python int GEM5_TOTAL_SIMULATION_PERIOD $GEM5_TOTAL_SIMULATION_PERIOD)
$(param_python int GEM5_REPORT_PERIOD_ps $GEM5_REPORT_PERIOD_ps)
$(param_python int MAX_INFLIGHT_TRANS $MAX_INFLIGHT_TRANS)
$(param_python int GEM5_MAX_BUFFER_SIZE $GEM5_MAX_BUFFER_SIZE)
$(param_python int GEM5_SYNCH_PERIOD_ps $GEM5_SYNCH_PERIOD_ps)
$(param_python int GEM5_SHORT_SLEEP_ns $GEM5_SHORT_SLEEP_ns)
$(param_python int GEM5_LONG_SLEEP_ns $GEM5_LONG_SLEEP_ns)
$(param_python int GEM5_TRAFFIC_ITT_ps $GEM5_TRAFFIC_ITT_ps)
$(param_python str GEM5_TRAFFIC_MODE $GEM5_TRAFFIC_MODE)
$(param_python str GEM5_TRAFFIC_PRINT_INJECTED $GEM5_TRAFFIC_PRINT_INJECTED)
$(param_python str GEM5_TRAFFIC_PRINT_RECEIVED $GEM5_TRAFFIC_PRINT_RECEIVED)
$(param_python int GEM5_TRAFFIC_NUM_TRANS $GEM5_TRAFFIC_NUM_TRANS)
$(param_python str SCENARIO_CASE_DIR $SCENARIO_CASE_DIR)
$(param_python str TOTAL_MEM_SIZE_MB "${TOTAL_MEM_SIZE_MB}MB")
$(param_python str DRAM_SCHEDULING_POLICY_GEM5 $DRAM_SCHEDULING_POLICY_GEM5)
$(param_python str GEM5_MEMTYPE $GEM5_MEMTYPE)
$(param_python str GEM5_PIM_MEMTYPE $GEM5_PIM_MEMTYPE)
$(param_python int NBITS_CH $NBITS_CH)
$(param_python int NBITS_LB $NBITS_LB)
$(param_python int NBITS_OF $NBITS_OF)
$(param_python int NBITS_RC $NBITS_RC)
$(param_python int DRAM_COLUMNS_PER_ROW $DRAM_COLUMNS_PER_ROW)
$(param_python str GEM5_SIMPLEMEMORY_LATENCY ${GEM5_SIMPLEMEMORY_LATENCY})
$(param_python str GEM5_SIMPLEMEMORY_BW ${GEM5_SIMPLEMEMORY_BW})
$(param_python int GEM5_SMCCONTROLLER_BUFFER_SIZE_REQ $GEM5_SMCCONTROLLER_BUFFER_SIZE_REQ)
$(param_python int GEM5_SMCCONTROLLER_BUFFER_SIZE_RSP $GEM5_SMCCONTROLLER_BUFFER_SIZE_RSP)
$(param_python str GEM5_SMCCONTROLLER_LATENCY "`perl -e "print ($GEM5_SMCCONTROLLER_LATENCY_cy/$HOST_CLOCK_FREQUENCY_GHz)"`ns")
$(param_python str VAULTCTRL_FRONTEND_LATENCY "`perl -e "print ($GEM5_VAULTCTRL_FRONTEND_LATENCY_cy * $DRAM_tCK)"`ns")
$(param_python str VAULTCTRL_BACKEND_LATENCY "`perl -e "print ($GEM5_VAULTCTRL_BACKEND_LATENCY_cy * $DRAM_tCK)"`ns")
$(param_python str DRAMCTRL_EXTRA_ROWBUFFER_SIZE "`perl -e "print ($DRAMCTRL_EXTRA_ROWBUFFER_SIZE)"`B")
$(param_python int GEM5_LINK_BUFFER_SIZE_REQ $GEM5_LINK_BUFFER_SIZE_REQ)
$(param_python int GEM5_LINK_BUFFER_SIZE_RSP $GEM5_LINK_BUFFER_SIZE_RSP)
$(param_python str GEM5_LINK_STATIC_LATENCY "`perl -e "print ($GEM5_SERDES_LATENCY_ns + $GEM5_LINK_LATENCY_ns)"`ns")
$(param_python int GEM5_TRAFFIC_IDLE_PERIOD_ps $GEM5_TRAFFIC_IDLE_PERIOD_ps)
$(param_python int GEM5_TRAFFIC_ACTIVE_PERIOD_ps $GEM5_TRAFFIC_ACTIVE_PERIOD_ps)
$(param_python str GEM5_RECORD_INJECTED_TRACES $GEM5_RECORD_INJECTED_TRACES)
$(param_python str GEM5_RECORD_FILE_NAME $GEM5_RECORD_FILE_NAME)
$(param_python str GEM5_EXTRAIMAGE $GEM5_EXTRAIMAGE)
$(param_python str HAVE_LISTENERS $HAVE_LISTENERS)
$(param_python str HAVE_PIM_DEVICE $HAVE_PIM_DEVICE)
$(param_python str NEW_PIM $NEW_PIM)
$(param_python str MOVE_PIM_TO_HOST $MOVE_PIM_TO_HOST)
$(param_python str DRAMSIM2_ENABLE_DEBUG $DRAMSIM2_ENABLE_DEBUG)
$(param_python str DRAMSIM2_ENABLE_TIMESTAMP $DRAMSIM2_ENABLE_TIMESTAMP)
$(param_python str HMON_DUMP_ADDRESS $HMON_DUMP_ADDRESS)
$(set_if_true $NEW_PIM "$(param_python int PIM_VAULT_BASE_ADDR $PIM_VAULT_BASE_ADDR)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str PIM_CLOCK_FREQUENCY ${PIM_CLOCK_FREQUENCY_GHz}GHz)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str GEM5_PIM_KERNEL $GEM5_PIM_KERNEL)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DEBUG_ADDR $PIM_DEBUG_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_ERROR_ADDR $PIM_ERROR_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_INTR_ADDR  $PIM_INTR_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_COMMAND_ADDR $PIM_COMMAND_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_STATUS_ADDR  $PIM_STATUS_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_SLICETABLE_ADDR $PIM_SLICETABLE+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_SLICECOUNT_ADDR $PIM_SLICECOUNT+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_SLICEVSTART_ADDR $PIM_SLICEVSTART+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_ADDRESS_BASE $PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str PIM_ADDRESS_SIZE $PIM_ADDRESS_SIZE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_ADDRESS_SIZE_INT $(conv_to_bytes $PIM_ADDRESS_SIZE))")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str PIM_SPM_ACCESSTIME_ns ${PIM_SPM_ACCESSTIME_ns}ns)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str PIM_SPM_BW_Gbps "${PIM_SPM_BW_Gbps}GB/s")")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_M5_ADDR $PIM_M5_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_M5_D1_ADDR $PIM_M5_D1_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_M5_D2_ADDR $PIM_M5_D2_REG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_VREG_ADDR $PIM_VREG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_VREG_SIZE $PIM_VREG_SIZE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_SREG_ADDR $PIM_SREG+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_SREG_COUNT $PIM_SREG_COUNT)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DTLB_IDEAL_REFILL_ADDR $PIM_DTLB_IDEAL_REFILL+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DTLB_IDEAL_REFILL_REG $PIM_DTLB_IDEAL_REFILL)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str PIM_DTLB_DO_IDEAL_REFILL $PIM_DTLB_DO_IDEAL_REFILL)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int HMC_ATOMIC_INCR $HMC_ATOMIC_INCR)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int HMC_ATOMIC_IMIN $HMC_ATOMIC_IMIN)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int HMC_ATOMIC_FADD $HMC_ATOMIC_FADD)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int HMC_OPERAND $HMC_OPERAND)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DTLB_SIZE $PIM_DTLB_SIZE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str OS_PAGE_SHIFT $OS_PAGE_SHIFT)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str PIM_DTLB_DUMP_ADDRESS $PIM_DTLB_DUMP_ADDRESS)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python str SMON_DUMP_ADDRESS $SMON_DUMP_ADDRESS)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DMA_MEM_ADDR_ADDR $PIM_DMA_MEM_ADDR+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DMA_SPM_ADDR_ADDR $PIM_DMA_SPM_ADDR+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DMA_NUMBYTES_ADDR $PIM_DMA_NUMBYTES+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DMA_COMMAND_ADDR $PIM_DMA_COMMAND+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DMA_STATUS_ADDR $PIM_DMA_STATUS+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_DMA_CLI_ADDR $PIM_DMA_CLI+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int HMC_ATOMIC_INCR_ADDR $HMC_ATOMIC_INCR+$PIM_ADDRESS_BASE)")
$(set_if_true $HAVE_PIM_DEVICE "$(param_python int PIM_COPROCESSOR_CMD_ADDR $PIM_COPROCESSOR_CMD+$PIM_ADDRESS_BASE)")
$(param_python str HAVE_PIM_CLUSTER $HAVE_PIM_CLUSTER)
" > $M5_OUTDIR/_gem5_params.py

###############################################################
if [ $GEM5_SIM_SCRIPT == ./configs/example/ethz_tgen.py ]; then		####### Traffic Based Simulation
	GEM5_EXECUTION_COMMAND="$(param_shell none "--debug-flags" $GEM5_DEBUGFLAGS) \
	$(param_shell none "--debug-file" $GEM5_DEBUGFILE) \
	--outdir=$M5_OUTDIR --path=$M5_OUTDIR $GEM5_VERBOSITY \
	$GEM5_SIM_SCRIPT \
	--mem-type=$GEM5_MEMTYPE"
###############################################################
elif [ $GEM5_SIM_SCRIPT == ./configs/example/ethz_fs.py ]; then     ####### Full System Simulation #JIWON: added num-pim-sys, pim-mem-type
    GEM5_EXECUTION_COMMAND="$(param_shell none "--debug-flags" $GEM5_DEBUGFLAGS) \
    $(param_shell none "--debug-file" $GEM5_DEBUGFILE) \
    --outdir=$M5_OUTDIR --path=$M5_OUTDIR $GEM5_VERBOSITY \
    $GEM5_SIM_SCRIPT \
    --cpu-type=$GEM5_CPUTYPE \
    --num-cpu=$GEM5_NUMCPU \
    --num-pim-sys=$NUM_PIM_DEVICES \
    --cpu-clock=${HOST_CLOCK_FREQUENCY_GHz}GHz \
    $(set_if_true $GEM5_AUTOMATED_SIMULATION "--script=$GEM5_AUTOMATED_SCRIPT") \
    $(set_if_true $HAVE_L1_CACHES "--caches") \
    $(set_if_true $HAVE_L2_CACHES "--l2cache") \
    --l1i_size=$L1I_CACHE_SIZE \
    --l1d_size=$L1D_CACHE_SIZE \
    --l2_size=$L2_CACHE_SIZE \
    $(set_if_true $GEM5_BARE_METAL_HOST "--bare-metal") \
    --mem-type=$GEM5_MEMTYPE \
    --pim-mem-type=$GEM5_PIM_MEMTYPE \
    --mem-size=${TOTAL_MEM_SIZE_MB}MB \
    --mem-channels=$N_INIT_PORT \
    --cacheline_size=$HOST_BURST_SIZE_B \
    $(param_shell none "--machine-type" $GEM5_MACHINETYPE) \
    $(param_shell none "--dtb-filename" $GEM5_DTBFILE) \
    $(param_shell none "--kernel" $GEM5_KERNEL) \
    $(param_shell none "--disk-image" $GEM5_DISKIMAGE)"
###############################################################
elif [ $GEM5_SIM_SCRIPT == ./configs/example/ethz_test.py ]; then	####### Test the closed loop simulation interface
	GEM5_EXECUTION_COMMAND="$(param_shell none "--debug-flags" $GEM5_DEBUGFLAGS) \
	$(param_shell none "--debug-file" $GEM5_DEBUGFILE) \
	--outdir=$M5_OUTDIR --path=$M5_OUTDIR $GEM5_VERBOSITY \
	$GEM5_SIM_SCRIPT \
	--mem-type=$GEM5_MEMTYPE"
###############################################################
else
	print_err "Illegal GEM5_SIM_SCRIPT: $GEM5_SIM_SCRIPT"
	exit
fi

### Restoring from checkpoint
if [ $GEM5_CHECKPOINT_RESTORE == "TRUE" ]; then
	cp -r $GEM5_CHECKPOINT_LOCATION $M5_OUTDIR/
	echo "Hello" > $M5_OUTDIR/CKPT_RESUMED
fi

### Gem5's Run Script
echo -e "#!/bin/bash
#Run script of gem5
print_msg \"Running ${COLOR_YELLOW}$GEM5_CONFIG - $GEM5_CPUTYPE\"
print_msg \"Total Memory Size: ${TOTAL_MEM_SIZE_MB}MB $(set_if_true $HAVE_PIM_DEVICE "PIM Memory Size: $PIM_ADDRESS_SIZE") \"
$(set_if_true $GEM5_CHECKPOINT_RESTORE "print_msg \"Restoring checkpoint $GEM5_CHECKPOINT_LOCATION\"")

_PWD=${PWD}
cd $SCENARIO_CASE_DIR
#######################
TIME1=\$(date +%s%N | cut -b1-13)
touch gem5_home_dir
./build/$GEM5_CONFIG --stats-file=stats_gem5.txt $GEM5_EXECUTION_COMMAND $(set_if_true $GEM5_CHECKPOINT_RESTORE "--checkpoint-restore=1  --restore-with-cpu=$GEM5_CPUTYPE")
TIME2=\$(date +%s%N | cut -b1-13)
#######################
echo \"DURATION_OF_SIMULATION_ms \$((\$TIME2-\$TIME1))\" >> $M5_OUTDIR/stats_gem5.txt
if [ \"$GEM5_CLOSEDLOOP_MODELSIM\" == \"TRUE\" ]; then
	print_msg \"Trying to close modelsim ...\"
	cd $M5_OUTDIR/
	echo \"!!! Killed by gem5 !!!\" > to_modelsim.pipe &
fi
returntopwd
" > $M5_OUTDIR/_gem5_run.sh
chmod +x $M5_OUTDIR/_gem5_run.sh

# DRAMSim2
if [ $HAVE_DRAMSIM == "TRUE" ]; then
	load_model memory/dramsim2_memory.sh > $M5_OUTDIR/dramsim2/HMC.ini
	load_model memory/dramsim2_system.sh > $M5_OUTDIR/dramsim2/HMC_System.ini
fi

###########################################################################
# Build gem5
if ! [ -z $__BUILD_GEM5 ]
then
	check_disk_images
 	check_external_tools

	echo -e "#!/bin/bash
	#Build script of gem5
	print_msg \"Building ${COLOR_YELLOW}$GEM5_CONFIG\"
	_PWD=${PWD}
	cd $GEM5_BASE_DIR
	scons build/$GEM5_CONFIG --colors -j6 --include-dir=$M5_OUTDIR
	returntopwd
	echo \"$GEM5_CONFIG was built successfully\"
	" > $M5_OUTDIR/_gem5_run.sh
	chmod +x $M5_OUTDIR/_gem5_run.sh
	export SHOW_STDOUT="TRUE"
fi
 
# Debug gem5
if ! [ -z $__DEBUG_GEM5 ]
then
	echo -e "#!/bin/bash
	#Debug script of gem5
	print_msg \"Debugging ${COLOR_YELLOW}$GEM5_CONFIG\"
	_PWD=${PWD}
	cd $SCENARIO_CASE_DIR
	echo -e \"
	file $GEM5_BASE_DIR/build/$GEM5_CONFIG
	run $GEM5_EXECUTION_COMMAND $(set_if_true $GEM5_CHECKPOINT_RESTORE "--checkpoint-restore=1  --restore-with-cpu=$GEM5_CPUTYPE")
	backtrace
	\" > $M5_OUTDIR/_gdb_commands.sh
	touch gem5_home_dir
	gdb -command=$M5_OUTDIR/_gdb_commands.sh
	returntopwd
	##### Information #####
	# (gdb) c
	# (gdb) backtrace
	# (gdb) run --debug-break=2000 configs/run.py 
	# (gdb) p curTick
	# (gdb) call schedBreakCycle(3000)
	# (gdb) p _curTick	
	" > $M5_OUTDIR/_gem5_run.sh
	chmod +x $M5_OUTDIR/_gem5_run.sh
	export SHOW_STDOUT="TRUE"
fi

# Closed loop simulation of modelsim and gem5
if ! [ $GEM5_CLOSEDLOOP_MODELSIM == "FALSE" ] && [ -z $LIST_PREVIOUS_RESULTS ]
then
	#########################################
	# Check if the shared memory is available
	#########################################
	printf "${COLOR_YELLOW}*** checking the shared memory ***\n${COLOR_NONE}"
	_PWD=$PWD
	cd $SMC_BASE_DIR
	ALLOCATE_SHM=FALSE
	if [ -e $SMC_BASE_DIR/UTILS/variables/SHMPID.txt ]; then
		set +e
		ID=$(cat $SMC_BASE_DIR/UTILS/variables/SHMPID.txt);
		FOUND=$(ipcs | grep $ID)
		set -e
		if [ -z "$FOUND" ] || [ "$FOUND" == "" ]; then
			ALLOCATE_SHM=TRUE
		fi
	else
		ALLOCATE_SHM=TRUE
	fi

	if [ $ALLOCATE_SHM == TRUE ]; then
		print_war "shared memory does not exist, allocating a new one"
		rm $SMC_BASE_DIR/UTILS/variables/SHMPID.txt -f
		#./UTILS/shmalloc
	fi
	
	
	cp $SMC_BASE_DIR/UTILS/variables/SHMPID.txt $M5_OUTDIR/
	cd $_PWD
	
	if [ $GEM5_CHECKPOINT_RESTORE == "TRUE" ]; then
		CYCLE=${GEM5_CHECKPOINT_LOCATION##/*/};
		CYCLE=${CYCLE:4}
		export VSIM_INIT_CYCLE=`perl -l -e "print (int($CYCLE/$CLK_PERIOD_SYS/1000))"`
		print_war "Restoring checkpoint in closed loop simulation, in ModelSim we will jump to Cycle $VSIM_INIT_CYCLE..."
	fi
	
	#....................
	echo "
	// Automatically generated by Erfan
	$(param_cpp int MAX_BUFFER_SIZE $GEM5_MAX_BUFFER_SIZE)
	$(param_cpp int SHORT_SLEEP $GEM5_SHORT_SLEEP_ns)
	$(param_cpp int LONG_SLEEP $GEM5_LONG_SLEEP_ns)
	$(param_cpp int SYNCH_PERIOD_ps $GEM5_SYNCH_PERIOD_ps)
	$(param_cpp str SCENARIO_CASE_DIR $SCENARIO_CASE_DIR)
	" > $SCENARIO_CASE_DIR/_dpi.h
	#....................
	cd $GEM5_PATH
	

	if [ $GEM5_CHECKPOINT_RESTORE == "FALSE" ]; then
		rm $M5_OUTDIR/to_modelsim.pipe -f
		rm $M5_OUTDIR/to_gem5.pipe -f
		mkfifo $M5_OUTDIR/to_modelsim.pipe			# Create a pipe gem5 --> modelsim
		mkfifo $M5_OUTDIR/to_gem5.pipe				# Create a pipe modelsim --> gem5
	else
		print_war "Keeping the existing pipes because a checkpoint is being resumed ..."
	fi
	
	if [ $GEM5_CPUTYPE == atomic ]; then
		clonedir $SMC_BASE_DIR/MISC/simplified-memory/dummy-memory
		cp $VSIM_BASE_DIR/TB/dpi.* .
		cp $SCENARIO_CASE_DIR/_dpi.h .
		make
		print_war "Running dummy-memory instead of ModelSim, because we are in atomic mode"
		./dummy-memory &
		cd $SMC_BASE_DIR
	else
		cd $VSIM_BASE_DIR
		source ./vsim.sh &
		sleep 1
		cd $SMC_BASE_DIR
	fi
fi

if [ -z $LIST_PREVIOUS_RESULTS ] && [ -z $__UPDATE_ONLY ] && ( [ -z $CONTINUE_SIMULATION ] || ! [ -f $M5_OUTDIR/stats_gem5.txt ]   ); then
	printf " ${COLOR_BOLD} [gem5] => ${COLOR_NONE}"
	if [ -z $SHOW_STDOUT ]; then
		source $M5_OUTDIR/_gem5_run.sh > $M5_OUTDIR/gem5.log 2>&1 &
	else
		source $M5_OUTDIR/_gem5_run.sh |& tee $M5_OUTDIR/gem5.log &
	fi
	wait
	
	if [ -z $__DEBUG_GEM5 ] && [ -z $__BUILD_GEM5 ]; then
		if [ $GEM5_AUTOMATED_SIMULATION == TRUE ] && [ $GEM5_CHECKPOINT_RESTORE == FALSE ]; then
			print_msg "Notice: In this simulation, we only took a checkpoint! Run again later to gather results."
			_PWD=${PWD}
			cd $M5_OUTDIR/
			NAME=$(ls -d cpt.*/);
			rm -rf $AUTOMATED_CHECKPOINT_DIR
			mkdir -p $AUTOMATED_CHECKPOINT_DIR/
			cp -r $NAME $AUTOMATED_CHECKPOINT_DIR/
			cd $_PWD
			
			if [ $GEM5_AUTOMATED_SIMULATION_MODE == homo ]; then
				print_msg "Only one checkpoint was enough for this scenario, so we exit now ..."
				exit
				# If hetero, we will continue to take checkpoints for all cases
			fi
		else
            report_gem5_stats
		fi
	else
		exit
	fi
else
	if ! [ -z $LIST_PREVIOUS_RESULTS ] && [ -z $__UPDATE_ONLY ]; then report_gem5_stats; fi
	unset __UPDATE_ONLY
fi



